#include "RotatingTriangle.h"

struct Vertex
{
	FLOAT x, y, z;
	DWORD color;
	static CONST DWORD FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
};

RotatingTriangle::RotatingTriangle(Graphic& graphic, INT width, INT height) 
{
	_Timer.SetTime(5);
	_Timer.Start();

	HRESULT hresult;
	_angle = 0.0f;

	// Set the projection matrix.
	D3DXMatrixPerspectiveFovLH(
		&_projection,
		D3DX_PI / 4,
		(float)width / height,
		0.1f,
		1000.0f
	);

	GetDevice(graphic)->SetTransform(D3DTS_PROJECTION, &_projection);

	// Set default rendering states.
	GetDevice(graphic)->SetRenderState(D3DRS_LIGHTING, FALSE);
	GetDevice(graphic)->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

	DWORD color = D3DCOLOR_XRGB(200, 0, 0);
	FLOAT r = 0.3f;

	std::vector<Vertex> v;

	FLOAT angle = -D3DX_PI / 4;
	Vertex a, b, c;
	for (int i = 0; i < 8; ++i) {
		a = { 0.0f, 0.0f, 1.0f, color };
		v.push_back(a);
		angle += D3DX_PI / 4;
		b = { r * (FLOAT)cos(angle), r * (FLOAT)sin(angle), 1.0f, color };
		v.push_back(b);
		angle += D3DX_PI / 4;
		c = { r * (FLOAT)cos(angle), r * (FLOAT)sin(angle), 1.0f, color };
		v.push_back(c);
		angle -= D3DX_PI / 4;
	}
	
	// Create the vertex buffer.
	hresult = GetDevice(graphic)->CreateVertexBuffer(
		v.size() * sizeof(Vertex),
		0,
		Vertex::FVF,
		D3DPOOL_DEFAULT,
		&_VertexBuffer,
		nullptr
	);
	if (FAILED(hresult))
		throw std::runtime_error("");
	
	// Fill the vertex buffer.
	void* ptr;
	hresult = _VertexBuffer->Lock(0, v.size() * sizeof(Vertex), (void**)&ptr, 0);
	if (FAILED(hresult))
		throw std::runtime_error("");
	memcpy(ptr, v.data(), v.size() * sizeof(Vertex));
	_VertexBuffer->Unlock();
}

RotatingTriangle::~RotatingTriangle() 
{

}

VOID RotatingTriangle::Draw(Graphic& graphic) 
{
	// Build translation and rotation matrices.
	D3DXMatrixTranslation(&_translation, 0.0f, 0.0f, 0.0f);
	D3DXMatrixRotationZ(&_rotation, _angle);

	// Build the world matrix and update angle.
	_worldMatrix = _rotation * _translation;
	if (_Timer.IsTimeOut()) {
		_angle += 0.01f;
	}
	if (_angle >= 360) {
		_angle = 0.0f;
	}

	// Set the world matrix.
	GetDevice(graphic)->SetTransform(D3DTS_WORLD, &_worldMatrix);

	// Draw the object.
	GetDevice(graphic)->SetStreamSource(0, _VertexBuffer.Get(), 0, sizeof(Vertex));
	GetDevice(graphic)->SetFVF(Vertex::FVF);
	GetDevice(graphic)->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 8);
}
